package network

import (
	"gitee.com/amoyx/cloud-provider/pkg/cloud/aliyun/models"
	alidns20150109 "github.com/alibabacloud-go/alidns-20150109/v4/client"
	openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client"
	util "github.com/alibabacloud-go/tea-utils/v2/service"
	"github.com/alibabacloud-go/tea/tea"
)

type DNSGreeter interface {
	DNS(region string) DNSInterface
}

type DNSInterface interface {
	DescribeDomains() (list []models.DescribeDomainsResponse, err error)
	DescribeInstanceDomains(instanceId string) (list []models.DescribeInstanceDomainsResponse, err error)
	DomainRequestCount(domain string, startDate string, endDate string) (count []int64, err error)
	DescribeDomainInfo(domain string) (result models.DescribeDomainInfoResponse, err error)
	AddDomainRecord(args models.DomainRecordRequest) (recordId string, err error)
	DeleteDomainRecord(recordId string) (err error)
	UpdateDomainRecord(args models.DomainRecordRequest) (err error)
	DescribeDomainRecords(domain string) (list []models.DescribeDomainRecordsResponse, err error)
	DescribeDomainRecordInfo(recordId string) (result models.DescribeDomainRecordsResponse, err error)
}

type dns struct {
	config *openapi.Config
	client *alidns20150109.Client
	region string
}

func newDNS(network *Network, region string) DNSInterface {
	v := &dns{
		config: network.config,
		region: region,
	}
	v.config.Endpoint = tea.String("alidns.cn-shanghai.aliyuncs.com")
	_client, _ := alidns20150109.NewClient(v.config)
	v.client = _client
	return v
}

// DescribeDomains 获取域名列表
func (d *dns) DescribeDomains() (list []models.DescribeDomainsResponse, err error) {
	request := &alidns20150109.DescribeDomainsRequest{
		PageNumber: tea.Int64(1),
		PageSize:   tea.Int64(100),
	}
	runtime := &util.RuntimeOptions{}
	response, err := d.client.DescribeDomainsWithOptions(request, runtime)
	if err != nil {
		return
	}
	for _, row := range response.Body.Domains.Domain {
		var servers []string
		for _, server := range row.DnsServers.DnsServer {
			servers = append(servers, *server)
		}
		list = append(list, models.DescribeDomainsResponse{
			DomainName:      *row.DomainName,
			DomainId:        *row.DomainId,
			AliDomain:       *row.AliDomain,
			VersionCode:     *row.VersionCode,
			VersionName:     *row.VersionName,
			CreateTimestamp: *row.CreateTimestamp,
			DnsServers:      servers,
			RecordCount:     *row.RecordCount,
			CreateTime:      *row.CreateTime,
			//Remark:          *row.Remark,
			//InstanceEndTime: *row.InstanceEndTime,
			//InstanceExpired: *row.InstanceExpired,
			//InstanceId:      *row.InstanceId,
			//RegistrantEmail: *row.RegistrantEmail,
		})
	}
	return
}

// DescribeInstanceDomains 获取实例域名列表
func (d *dns) DescribeInstanceDomains(instanceId string) (list []models.DescribeInstanceDomainsResponse, err error) {
	request := &alidns20150109.DescribeInstanceDomainsRequest{
		InstanceId: tea.String(instanceId),
		PageNumber: tea.Int64(1),
		PageSize:   tea.Int64(100),
	}
	runtime := &util.RuntimeOptions{}
	response, err := d.client.DescribeInstanceDomainsWithOptions(request, runtime)
	if err != nil {
		return
	}
	for _, row := range response.Body.InstanceDomains {
		list = append(list, models.DescribeInstanceDomainsResponse{
			DomainName:      *row.DomainName,
			CreateTime:      *row.CreateTime,
			CreateTimestamp: *row.CreateTimestamp,
		})
	}
	return
}

// DomainRequestCount 域名请求量
func (d *dns) DomainRequestCount(domain string, startDate string, endDate string) (count []int64, err error) {
	describeDomainStatisticsRequest := &alidns20150109.DescribeDomainStatisticsRequest{
		DomainName: tea.String(domain),
		StartDate:  tea.String(startDate),
		EndDate:    tea.String(endDate),
	}
	runtime := &util.RuntimeOptions{}
	response, err := d.client.DescribeDomainStatisticsWithOptions(describeDomainStatisticsRequest, runtime)
	if err != nil {
		return
	}
	for _, val := range response.Body.Statistics.Statistic {
		count = append(count, *val.Count)
	}
	return
}

// DescribeDomainInfo 域名信息
func (d *dns) DescribeDomainInfo(domain string) (result models.DescribeDomainInfoResponse, err error) {
	describeDomainInfoRequest := &alidns20150109.DescribeDomainInfoRequest{
		DomainName: tea.String(domain),
	}
	runtime := &util.RuntimeOptions{}
	response, err := d.client.DescribeDomainInfoWithOptions(describeDomainInfoRequest, runtime)
	if err != nil {
		return
	}
	result.DomainName = *response.Body.DomainName
	result.DomainId = *response.Body.DomainId
	result.Remark = *response.Body.Remark
	result.VersionCode = *response.Body.VersionCode
	result.VersionName = *response.Body.VersionName
	result.InstanceId = *response.Body.InstanceId
	result.CreateTime = *response.Body.CreateTime
	for _, server := range response.Body.DnsServers.DnsServer {
		result.DnsServers = append(result.DnsServers, *server)
	}
	for _, line := range response.Body.RecordLines.RecordLine {
		result.RecordLines = append(result.RecordLines, models.DescribeDomainRecordLine{
			FatherCode:      *line.FatherCode,
			LineCode:        *line.LineCode,
			LineName:        *line.LineName,
			LineDisplayName: *line.LineDisplayName,
		})
	}
	return
}

// AddDomainRecord 添加域名解析记录
func (d *dns) AddDomainRecord(args models.DomainRecordRequest) (recordId string, err error) {
	request := &alidns20150109.AddDomainRecordRequest{
		DomainName: tea.String(args.DomainName),
		RR:         tea.String(args.RR),
		Type:       tea.String(args.RecordType),
		Value:      tea.String(args.Value),
		TTL:        tea.Int64(args.TTL),
		Line:       tea.String("default"),
	}
	if args.RecordType == "MX" {
		request.Priority = tea.Int64(args.Priority)
	}
	runtime := &util.RuntimeOptions{}
	response, err := d.client.AddDomainRecordWithOptions(request, runtime)
	if err != nil {
		return
	}
	recordId = *response.Body.RecordId
	return
}

// DeleteDomainRecord 删除域名解析记录
func (d *dns) DeleteDomainRecord(recordId string) (err error) {
	deleteDomainRecordRequest := &alidns20150109.DeleteDomainRecordRequest{
		RecordId: tea.String(recordId),
	}
	runtime := &util.RuntimeOptions{}
	_, err = d.client.DeleteDomainRecordWithOptions(deleteDomainRecordRequest, runtime)
	return
}

// UpdateDomainRecord 修改域名解析记录
func (d *dns) UpdateDomainRecord(args models.DomainRecordRequest) (err error) {
	request := &alidns20150109.UpdateDomainRecordRequest{
		RecordId: tea.String(args.RecordId),
		RR:       tea.String(args.RR),
		Type:     tea.String(args.RecordType),
		Value:    tea.String(args.Value),
		TTL:      tea.Int64(args.TTL),
		Line:     tea.String("default"),
	}
	if args.RecordType == "MX" {
		request.Priority = tea.Int64(args.Priority)
	}
	runtime := &util.RuntimeOptions{}
	_, err = d.client.UpdateDomainRecordWithOptions(request, runtime)
	return
}

// DescribeDomainRecords 获取域名解析记录
func (d *dns) DescribeDomainRecords(domain string) (list []models.DescribeDomainRecordsResponse, err error) {
	describeDomainRecordsRequest := &alidns20150109.DescribeDomainRecordsRequest{
		DomainName: tea.String(domain),
		PageNumber: tea.Int64(1),
		PageSize:   tea.Int64(500),
	}
	runtime := &util.RuntimeOptions{}
	response, err := d.client.DescribeDomainRecordsWithOptions(describeDomainRecordsRequest, runtime)
	if err != nil {
		return
	}
	for _, row := range response.Body.DomainRecords.Record {
		var priority int64
		var weight int32
		if row.Priority != nil {
			priority = *row.Priority
		}
		if row.Weight != nil {
			weight = *row.Weight
		}
		list = append(list, models.DescribeDomainRecordsResponse{
			CreateTimestamp: *row.CreateTimestamp,
			DomainName:      *row.DomainName,
			RecordId:        *row.RecordId,
			RR:              *row.RR,
			Type:            *row.Type,
			Value:           *row.Value,
			TTL:             *row.TTL,
			Priority:        priority,
			Line:            *row.Line,
			Status:          *row.Status,
			Locked:          *row.Locked,
			Weight:          weight,
		})
	}
	return
}

// DescribeDomainRecordInfo 获取域名指定记录信息
func (d *dns) DescribeDomainRecordInfo(recordId string) (result models.DescribeDomainRecordsResponse, err error) {
	describeDomainRecordInfoRequest := &alidns20150109.DescribeDomainRecordInfoRequest{
		RecordId: tea.String(recordId),
	}
	runtime := &util.RuntimeOptions{}
	response, err := d.client.DescribeDomainRecordInfoWithOptions(describeDomainRecordInfoRequest, runtime)
	if err != nil {
		return
	}
	row := response.Body
	var priority int64
	if row.Priority != nil {
		priority = *row.Priority
	}
	result = models.DescribeDomainRecordsResponse{
		DomainName: *row.DomainName,
		RecordId:   *row.RecordId,
		RR:         *row.RR,
		Type:       *row.Type,
		Value:      *row.Value,
		TTL:        *row.TTL,
		Priority:   priority,
		Line:       *row.Line,
		Status:     *row.Status,
		Locked:     *row.Locked,
	}
	return
}
